/*
 * Copyright 2002-2006 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 control.add(getTaskPanel(), "0, 0, 1, 3");
 * License for the specific language governing permissions and limitations under
 * the License.
 import com.jgoodies.forms.layout.FormLayout;
 */
package net.jwtools.tmt.ui;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.sql.SQLException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

import net.jwtools.tmt.domain.IVisit;
import net.jwtools.tmt.domain.Territory;
import net.jwtools.tmt.service.IVisitService;
import net.jwtools.tmt.service.TerritoryService;
import net.jwtools.tmt.ui.table.VisitsTable;

import org.jdesktop.swingx.JXPanel;
import org.springframework.binding.value.ValueModel;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.richclient.application.PageComponentContext;
import org.springframework.richclient.application.event.LifecycleApplicationEvent;
import org.springframework.richclient.application.support.AbstractView;
import org.springframework.richclient.command.ActionCommand;
import org.springframework.richclient.command.CommandGroup;
import org.springframework.richclient.command.GuardedActionCommandExecutor;
import org.springframework.richclient.command.support.AbstractActionCommandExecutor;
import org.springframework.richclient.command.support.GlobalCommandIds;
import org.springframework.richclient.dialog.ConfirmationDialog;
import org.springframework.richclient.list.ListSelectionValueModelAdapter;
import org.springframework.richclient.list.ListSingleSelectionGuard;

import ca.odell.glazedlists.EventList;
import ca.odell.glazedlists.FilterList;


public class CheckoutView extends AbstractView implements ApplicationListener {
	/**
	 * Handler for the "New Contact" action.
	 */
	private GuardedActionCommandExecutor checkoutExecutor = new CheckoutExecutor();

	/**
	 * Handler for the "Properties" action.
	 */
	private GuardedActionCommandExecutor detailsExecutor = new DetailsExecutor();

	/**
	 * Handler for the "Delete" action.
	 */
	private GuardedActionCommandExecutor deleteExecutor = new DeleteExecutor();

	/**
	 * The text field allowing the user to filter the contents of the contact
	 * table.
	 */
	private TerritoryMapViewer imagePanel;
	private JSplitPane tableAndDetailJSplitPane;

	private JXPanel detailPanel;

	private JXPanel detailInfo;

	private TerritoryTypeMatcherEditor territoryTypeMatcher;

	private VisitTypeMatcherEditor visitTypeMatcher;
	
	private JPanel filterPanel;

	private VisitsTable visitsTable;

	private TerritoryInfoForm infoForm;
	{
		// Set Look & Feel
		try {
			javax.swing.UIManager
					.setLookAndFeel("com.jgoodies.looks.plastic.Plastic3DLookAndFeel");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private IVisitService visitService;

	/**
	 * Default constructor.
	 */
	public CheckoutView() {
	}

	public IVisitService getVisitService() {
		return visitService;
	}

	public void setVisitService(IVisitService visitService) {
		this.visitService = visitService;
	}

	protected void initListeners() {

	}

	/**
	 * Register the local command executors to be associated with named
	 * commands. This is called by the platform prior to making the view
	 * visible.
	 */
	protected void registerLocalCommandExecutors(PageComponentContext context) {
		context.register("checkoutCommand", checkoutExecutor);
		context.register(GlobalCommandIds.DELETE, deleteExecutor);
	}

	/**
	 * Handle an application event. This will notify us of object adds, deletes,
	 * and modifications. Forward to our object table for handling.
	 * 
	 * @param e
	 *            event to process
	 */
	public void onApplicationEvent(ApplicationEvent e) {
		visitsTable.onApplicationEvent(e);
	}

	@Override
	protected JComponent createControl() {
		return createCheckoutPanel();
	}

	protected JComponent createCheckoutButtonPanel() {
		JPanel checkoutButtonJPanel = new JPanel();
		FlowLayout checkoutButtonJPanelLayout = new FlowLayout();
		checkoutButtonJPanel.setLayout(checkoutButtonJPanelLayout);
		JButton deleteButton = (JButton) ((ActionCommand) getWindowCommandManager()
				.getCommand(GlobalCommandIds.DELETE)).createButton();
		checkoutButtonJPanel.add(deleteButton);
		JButton checkOutButton = (JButton) ((ActionCommand) getWindowCommandManager()
				.getCommand("checkoutCommand")).createButton();
		checkoutButtonJPanel.add(checkOutButton);
		return checkoutButtonJPanel;
	}

	protected JComponent createCheckoutPanel() {
		JPanel checkoutJPanel = new JPanel();
		BorderLayout checkoutJPanelLayout = new BorderLayout();

		checkoutJPanel.setLayout(checkoutJPanelLayout);
		checkoutJPanel.add(getTableAndDetailJSplitPane(), BorderLayout.CENTER);

		JPanel filterJPanel = new JPanel();
		BorderLayout filterJPanelLayout = new BorderLayout();
		filterJPanel.setLayout(filterJPanelLayout);
		
		filterJPanel.add(visitTypeMatcher.getComponent(), BorderLayout.NORTH);
		visitTypeMatcher.getComponent().setMinimumSize(new Dimension(100, 200));
		filterJPanel.add(territoryTypeMatcher.getComponent(), BorderLayout.CENTER);
		territoryTypeMatcher.getComponent().setMinimumSize(new Dimension(100, 200));
		checkoutJPanel.add(filterJPanel,BorderLayout.WEST);
		return checkoutJPanel;
	}

	/**
	 * Prepare the table holding all the Contact objects. This table provides
	 * pretty much all the functional operations within this view. Prior to
	 * calling this method the {@link #setContactTable(VisitsTable)} will have
	 * already been called as part of the context bean creation.
	 */

	public VisitsTable createVisitsTable() {
		visitsTable = new VisitsTable();
		visitsTable.setDoubleClickHandler(checkoutExecutor);
		visitsTable.setClickHandler(detailsExecutor);
		EventList<IVisit> baseList = visitsTable.getBaseEventList();
		
		territoryTypeMatcher = new TerritoryTypeMatcherEditor(baseList);
		
		FilterList<IVisit> territoryTypeList = new FilterList<IVisit>(baseList, territoryTypeMatcher);
		
		visitTypeMatcher = new VisitTypeMatcherEditor(territoryTypeList);
		FilterList<IVisit> visitTypeList = new FilterList<IVisit>(territoryTypeList, visitTypeMatcher);
		
		visitsTable.setFinalEventList(visitTypeList);

		// Install the popup menu
		CommandGroup popup = new CommandGroup();
		popup.add((ActionCommand) getWindowCommandManager().getCommand(
				"deleteCommand", ActionCommand.class));
		popup.addSeparator();
		popup.add((ActionCommand) getWindowCommandManager().getCommand(
				"propertiesCommand", ActionCommand.class));
		visitsTable.setPopupCommandGroup(popup);
		visitsTable.setStatusBar(getStatusBar());
		ValueModel selectionHolder = new ListSelectionValueModelAdapter(
				visitsTable.getSelectionModel());
		new ListSingleSelectionGuard(selectionHolder, deleteExecutor);
		new ListSingleSelectionGuard(selectionHolder, detailsExecutor);
		new ListSingleSelectionGuard(selectionHolder, checkoutExecutor);

		return visitsTable;
	}

	private JSplitPane getTableAndDetailJSplitPane() {
		if (tableAndDetailJSplitPane == null) {
			tableAndDetailJSplitPane = new JSplitPane();
			tableAndDetailJSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
			JScrollPane sp = getComponentFactory().createScrollPane(
					createVisitsTable().getControl());

			BorderLayout tablePanelLayout = new BorderLayout();
			JPanel tablePanel = new JPanel(tablePanelLayout);
			tablePanel.add(sp, BorderLayout.CENTER);
			tablePanel.add(createCheckoutButtonPanel(), BorderLayout.SOUTH);
			tableAndDetailJSplitPane.add(tablePanel, JSplitPane.LEFT);
			sp.setPreferredSize(new java.awt.Dimension(550, 250));
		}
		detailPanel = new JXPanel();
		detailPanel.setLayout(new BorderLayout());
		imagePanel = new TerritoryMapViewer();
		detailPanel.add(imagePanel, BorderLayout.CENTER);
		detailInfo = new JXPanel();
		detailPanel.add(detailInfo, BorderLayout.EAST);
		tableAndDetailJSplitPane.add(detailPanel, JSplitPane.RIGHT);
		detailInfo.setPreferredSize(new java.awt.Dimension(300, 200));
		detailInfo.setMaximumSize(new java.awt.Dimension(300, 200));
		return tableAndDetailJSplitPane;
	}

	/**
	 * Private inner class to create a new contact.
	 */
	private class CheckoutExecutor extends AbstractActionCommandExecutor {
		public void execute() {
			final IVisit visit = visitsTable.getSelectedVisit();
			new TerritoryCheckoutDialog(visit, getVisitService()).showDialog();
		}
	}

	private class DetailsExecutor extends AbstractActionCommandExecutor {
		public void execute() {
			final IVisit visit = visitsTable.getSelectedVisit();
			BufferedImage image = null;
			Territory territory = null;
			String info = "test";
			if (visit != null) {
				TerritoryService ts = (TerritoryService) getApplicationServices()
						.getService(TerritoryService.class);
				territory = ts.getFullTerritoryById(visit.getTerritory()
						.getId());
				info = territory.getNumber() + territory.getDescription();
				try {
					if (territory.getMap() != null) {
						image = ImageIO.read(territory.getMap()
								.getBinaryStream());
					}
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				} catch (SQLException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			imagePanel.setOverview(image);
			if (infoForm == null) {
				infoForm = new TerritoryInfoForm(territory);
				detailInfo.add(infoForm.createFormControl());
				tableAndDetailJSplitPane.validate();
			} else {
				infoForm.setFormObject(territory);
			}

		}
	}

	/**
	 * Private class to handle the delete command. Note that due to the
	 * configuration above, this executor is only enabled when exactly one
	 * contact is selected in the table. Thus, we don't have to protect against
	 * being executed with an incorrect state.
	 */
	private class DeleteExecutor extends AbstractActionCommandExecutor {
		public void execute() {
			// We know exactly one contact will be selected at this time because
			// of the guards put in place in prepareTable.
			final IVisit visit = visitsTable.getSelectedVisit();
			// Query the user to be sure they want to do this
			String title = getMessage("contact.confirmDelete.title");
			String message = getMessage("contact.confirmDelete.message");
			ConfirmationDialog dlg = new ConfirmationDialog(title, message) {
				protected void onConfirm() {
					// Delete the object from the persistent store.
					// getContactDataStore().delete(visit);
					// And notify the rest of the application of the change
					getApplicationContext().publishEvent(
							new LifecycleApplicationEvent(
									LifecycleApplicationEvent.DELETED, visit));
				}
			};
			dlg.showDialog();
		}
	}

}